package com.tange365.openapi.util;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Arrays;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class SignatureUtil {
    private static final String MAC_NAME = "HmacSHA1";
    private static final String ENCODING = "UTF-8";
    private static final char[] HEX_CHAR_TABLE = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    public static String calcSignature(HashMap<String, String> map, String secret) {
        ArrayList<String> stringList = new ArrayList<>();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            stringList.add(String.format("%s=%s", entry.getKey(), entry.getValue()));
        }

        Collections.sort(stringList);

        String data = String.join("&",stringList);
        String encode = Base64.getEncoder().encodeToString(data.getBytes());

        return toHexString(HmacSHA1Encrypt(encode, secret));
    }

    private static byte[] HmacSHA1Encrypt(String encryptText, String encryptKey) {
        try {
            byte[]  key = encryptKey.getBytes(ENCODING);
            SecretKey secretKey = new SecretKeySpec(key, MAC_NAME);
            Mac mac = Mac.getInstance(MAC_NAME);
            mac.init(secretKey);

            byte[] text = encryptText.getBytes(ENCODING);
            return mac.doFinal(text);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }

        return null;
    }

    private static String toHexString(byte[] bytes) {
        if (bytes == null) {
            return "";
        }

        StringBuffer buffer=new StringBuffer("");
        for ( int i = 0; i <bytes.length ; i++ ) {
            int v=bytes[i];
            buffer.append(HEX_CHAR_TABLE[(v & 0xF0) >>> 4]);
            buffer.append(HEX_CHAR_TABLE[v & 0x0F]);
        }
        return buffer.toString();
    }
}
